﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Se.Reflection
{
    /// <summary>
    /// Db缓存类
    /// </summary>
    public class ReflectionManager
    {
        private static ConcurrentDictionary<Type, FastFieldInfo[]> _fieldInfoSet { get; set; }
        private static ConcurrentDictionary<Type, FastPropertyInfo[]> _propertyInfoSet { get; set; }


        public static FastFieldInfo[] GetFields(Type type)
        {
            if (_fieldInfoSet == null)
            {
                _fieldInfoSet = new ConcurrentDictionary<Type, FastFieldInfo[]>();
            }

            if (!_fieldInfoSet.ContainsKey(type))
            {
                var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).ToList();
                var fastFields = new List<FastFieldInfo>();
                fields.ForEach(field => { fastFields.Add(new FastFieldInfo(field)); });
                _fieldInfoSet[type] = fastFields.ToArray();
            }

            return _fieldInfoSet[type];
        }

        public static FastPropertyInfo[] GetProperties(Type type)
        {
            if (_propertyInfoSet == null)
            {
                _propertyInfoSet = new ConcurrentDictionary<Type, FastPropertyInfo[]>();
            }

            if (!_propertyInfoSet.ContainsKey(type))
            {
                var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).ToList();
                var fastProperties = new List<FastPropertyInfo>();
                properties.ForEach(property => { fastProperties.Add(new FastPropertyInfo(property)); });
                _propertyInfoSet[type] = fastProperties.ToArray();
            }

            return _propertyInfoSet[type];
        }

    }

    public class FastFieldInfo
    {
        public FastFieldInfo(FieldInfo field)
        {
            this.CurrentField = field;
            this.FieldAccessor = FastReflectionCaches.FieldAccessorCache.Get(field);
        }

        public FieldInfo CurrentField { get; private set; }

        public IFieldAccessor FieldAccessor { get; private set; }
    }

    public class FastPropertyInfo
    {
        public FastPropertyInfo(PropertyInfo property)
        {
            this.CurrentProperty = property;
            this.PropertyAccessor = FastReflectionCaches.PropertyAccessorCache.Get(property);
        }

        public PropertyInfo CurrentProperty { get; private set; }

        public IPropertyAccessor PropertyAccessor { get; private set; }
    }
}
